package org.funtester.performance.books.chapter03.section3;

import org.funtester.performance.books.chapter03.section4.TaskExecutor;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 多线程任务类
 */
public abstract class ThreadTask implements Runnable {


    /**
     * 全局是否终止测试任务开关
     */
    public static AtomicBoolean ABORT = new AtomicBoolean(false);

    /**
     * 是否终止单个任务执行开关
     */
    public boolean needStop = false;

    /**
     * 执行的总次数
     */
    public int totalNum;

    /**
     * 执行次数
     */
    public int executeNum = 0;

    /**
     * 执行错误次数
     */
    public int errorNum = 0;

    /**
     * 用于停止任务的计数器
     */
    public CountDownLatch stopCountDownLatch;

    /**
     * 用于Rump-Up功能,标识线程已经启动
     */
    public CountDownLatch rumpUpCountDownLatch;

    /**
     * 用于标识是否统计响应时间
     */
    public boolean countState = false;

    /**
     * 用于记录所有请求时间
     */
    public List<Integer> costTime;

    /**
     * 多线程任务执行方法
     */
    @Override
    public void run() {
        rumpUpCountDownLatch.countDown();// 计数器减一
        try {
            before();// 前置处理
            while (true) {
                if (ABORT.get() || needStop || executeNum >= totalNum) {// 判断是否终止测试任务
                    break;
                }
                try {
                    long start = System.currentTimeMillis();// 记录开始时间
                    test();// 测试方法
                    long end = System.currentTimeMillis();// 记录结束时间
                    int delay = (int) (end - start);
                    TaskExecutor.realTimeCostTime.add(delay);// 记录实时执行时间
                    TaskExecutor.realTimeCostTimes.add(1);// 记录实时执行次数
                    if (countState) {
                        executeNum++;// 记录执行次数
                        costTime.add(delay);
                    }
                } catch (Exception e) {
                    if (countState) errorNum++;// 记录错误次数
                    e.printStackTrace();
                }
            }
            after();// 后置处理
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            stopCountDownLatch.countDown();// 计数器减一
        }
    }

    /**
     * 前置处理方法,将统计数据重置为默认值
     */
    public void before() {
        executeNum = 0;
        errorNum = 0;
        needStop = false;
        countState = false;
        ABORT.set(false);
        if (costTime != null) costTime.clear();
    }

    /**
     * 测试方法
     */
    public abstract void test();

    /**
     * 后置处理方法
     */
    public void after() {
        ABORT.set(true);// 终止测试任务
        System.out.println(String.format("任务执行完毕! 预期执行次数: %d, 实际执行次数 %d, 错误次数 %d, 耗时收集数量: %d", totalNum, executeNum, errorNum, costTime.size()));// 打印任务执行完毕
    }


}
